using Lzfy_His_Service.Models;
using Lzfy_His_Service.Repositories;

namespace Lzfy_His_Service.Services
{
    public class RefundTaskDetailService : IRefundTaskDetailService
    {
        private readonly IRefundTaskDetailRepository _repository;
        private readonly ILogger<RefundTaskDetailService> _logger;

        public RefundTaskDetailService(
            IRefundTaskDetailRepository repository,
            ILogger<RefundTaskDetailService> logger)
        {
            _repository = repository;
            _logger = logger;
        }

        public async Task<RefundTaskDetailResponse?> GetByIdAsync(long id)
        {
            try
            {
                var detail = await _repository.GetByIdAsync(id);
                if (detail == null) return null;

                return new RefundTaskDetailResponse
                {
                    Id = detail.Id,
                    InputDate = detail.InputDate,
                    MasterId = detail.MasterId,
                    PatientId = detail.PatientId,
                    AccountId = detail.AccountId,
                    AccountIndex = detail.AccountIndex,
                    Balance = detail.Balance,
                    ContactCount = detail.ContactCount,
                    ContactTime1 = detail.ContactTime1?.ToLocalTime(),
                    ContactTime2 = detail.ContactTime2?.ToLocalTime(),
                    ContactTime3 = detail.ContactTime3?.ToLocalTime(),
                    ContactTime4 = detail.ContactTime4?.ToLocalTime(),
                    ContactTime5 = detail.ContactTime5?.ToLocalTime(),
                    PhoneNumber = detail.PhoneNumber,
                    PatName = detail.PatName,
                    IdNumber = detail.IdNumber,
                    Sex = detail.Sex,
                    NextOfKin = detail.NextOfKin,
                    NextOfKinPhone = detail.NextOfKinPhone,
                    GuardianName = detail.GuardianName,
                    GuardianIdcode = detail.GuardianIdcode,
                    Notes1 = detail.Notes1,
                    Notes2 = detail.Notes2,
                    Notes3 = detail.Notes3,
                    Notes4 = detail.Notes4,
                    Notes5 = detail.Notes5,
                    UserNotes1 = detail.UserNotes1,
                    UserNotes2 = detail.UserNotes2,
                    UserNotes3 = detail.UserNotes3,
                    UserNotes4 = detail.UserNotes4,
                    UserNotes5 = detail.UserNotes5
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task detail by id: {Id}", id);
                throw;
            }
        }

        public async Task<IEnumerable<RefundTaskDetailResponse>> GetAllAsync()
        {
            try
            {
                var details = await _repository.GetAllAsync();
                return details.Select(d => new RefundTaskDetailResponse
                {
                    Id = d.Id,
                    InputDate = d.InputDate,
                    MasterId = d.MasterId,
                    PatientId = d.PatientId,
                    AccountId = d.AccountId,
                    AccountIndex = d.AccountIndex,
                    Balance = d.Balance,
                    ContactCount = d.ContactCount,
                    ContactTime1 = d.ContactTime1?.ToLocalTime(),
                    ContactTime2 = d.ContactTime2?.ToLocalTime(),
                    ContactTime3 = d.ContactTime3?.ToLocalTime(),
                    ContactTime4 = d.ContactTime4?.ToLocalTime(),
                    ContactTime5 = d.ContactTime5?.ToLocalTime(),
                    PhoneNumber = d.PhoneNumber,
                    PatName = d.PatName,
                    IdNumber = d.IdNumber,
                    Sex = d.Sex,
                    NextOfKin = d.NextOfKin,
                    NextOfKinPhone = d.NextOfKinPhone,
                    GuardianName = d.GuardianName,
                    GuardianIdcode = d.GuardianIdcode,
                    Notes1 = d.Notes1,
                    Notes2 = d.Notes2,
                    Notes3 = d.Notes3,
                    Notes4 = d.Notes4,
                    Notes5 = d.Notes5,
                    UserNotes1 = d.UserNotes1,
                    UserNotes2 = d.UserNotes2,
                    UserNotes3 = d.UserNotes3,
                    UserNotes4 = d.UserNotes4,
                    UserNotes5 = d.UserNotes5
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting all refund task details");
                throw;
            }
        }

        public async Task<IEnumerable<RefundTaskDetailResponse>> GetByMasterIdAsync(long masterId)
        {
            try
            {
                var details = await _repository.GetByMasterIdAsync(masterId);
                return details.Select(d => new RefundTaskDetailResponse
                {
                    Id = d.Id,
                    InputDate = d.InputDate,
                    MasterId = d.MasterId,
                    PatientId = d.PatientId,
                    AccountId = d.AccountId,
                    AccountIndex = d.AccountIndex,
                    Balance = d.Balance,
                    ContactCount = d.ContactCount,
                    ContactTime1 = d.ContactTime1?.ToLocalTime(),
                    ContactTime2 = d.ContactTime2?.ToLocalTime(),
                    ContactTime3 = d.ContactTime3?.ToLocalTime(),
                    ContactTime4 = d.ContactTime4?.ToLocalTime(),
                    ContactTime5 = d.ContactTime5?.ToLocalTime(),
                    PhoneNumber = d.PhoneNumber,
                    PatName = d.PatName,
                    IdNumber = d.IdNumber,
                    Sex = d.Sex,
                    NextOfKin = d.NextOfKin,
                    NextOfKinPhone = d.NextOfKinPhone,
                    GuardianName = d.GuardianName,
                    GuardianIdcode = d.GuardianIdcode,
                    Notes1 = d.Notes1,
                    Notes2 = d.Notes2,
                    Notes3 = d.Notes3,
                    Notes4 = d.Notes4,
                    Notes5 = d.Notes5,
                    UserNotes1 = d.UserNotes1,
                    UserNotes2 = d.UserNotes2,
                    UserNotes3 = d.UserNotes3,
                    UserNotes4 = d.UserNotes4,
                    UserNotes5 = d.UserNotes5
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task details by master id: {MasterId}", masterId);
                throw;
            }
        }

        public async Task<(IEnumerable<RefundTaskDetailResponse> data, int totalCount)> GetWithFilterAsync(RefundTaskDetailQueryRequest request)
        {
            try
            {
                var (details, totalCount) = await _repository.GetWithFilterAsync(
                    request.MasterId,
                    request.PatientId,
                    request.PatName,
                    request.PhoneNumber,
                    request.ContactCount,
                    request.StartDate,
                    request.EndDate,
                    request.PageIndex,
                    request.PageSize);

                var responses = details.Select(d => new RefundTaskDetailResponse
                {
                    Id = d.Id,
                    InputDate = d.InputDate,
                    MasterId = d.MasterId,
                    PatientId = d.PatientId,
                    AccountId = d.AccountId,
                    AccountIndex = d.AccountIndex,
                    Balance = d.Balance,
                    ContactCount = d.ContactCount,
                    ContactTime1 = d.ContactTime1?.ToLocalTime(),
                    ContactTime2 = d.ContactTime2?.ToLocalTime(),
                    ContactTime3 = d.ContactTime3?.ToLocalTime(),
                    ContactTime4 = d.ContactTime4?.ToLocalTime(),
                    ContactTime5 = d.ContactTime5?.ToLocalTime(),
                    PhoneNumber = d.PhoneNumber,
                    PatName = d.PatName,
                    IdNumber = d.IdNumber,
                    Sex = d.Sex,
                    NextOfKin = d.NextOfKin,
                    NextOfKinPhone = d.NextOfKinPhone,
                    GuardianName = d.GuardianName,
                    GuardianIdcode = d.GuardianIdcode,
                    Notes1 = d.Notes1,
                    Notes2 = d.Notes2,
                    Notes3 = d.Notes3,
                    Notes4 = d.Notes4,
                    Notes5 = d.Notes5,
                    UserNotes1 = d.UserNotes1,
                    UserNotes2 = d.UserNotes2,
                    UserNotes3 = d.UserNotes3,
                    UserNotes4 = d.UserNotes4,
                    UserNotes5 = d.UserNotes5
                });

                return (responses, totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task details with filter");
                throw;
            }
        }

        public async Task<IEnumerable<RefundTaskDetailResponse>> GetByPatientIdAsync(string patientId)
        {
            try
            {
                var details = await _repository.GetByPatientIdAsync(patientId);
                return details.Select(d => new RefundTaskDetailResponse
                {
                    Id = d.Id,
                    InputDate = d.InputDate,
                    MasterId = d.MasterId,
                    PatientId = d.PatientId,
                    AccountId = d.AccountId,
                    AccountIndex = d.AccountIndex,
                    Balance = d.Balance,
                    ContactCount = d.ContactCount,
                    ContactTime1 = d.ContactTime1?.ToLocalTime(),
                    ContactTime2 = d.ContactTime2?.ToLocalTime(),
                    ContactTime3 = d.ContactTime3?.ToLocalTime(),
                    ContactTime4 = d.ContactTime4?.ToLocalTime(),
                    ContactTime5 = d.ContactTime5?.ToLocalTime(),
                    PhoneNumber = d.PhoneNumber,
                    PatName = d.PatName,
                    IdNumber = d.IdNumber,
                    Sex = d.Sex,
                    NextOfKin = d.NextOfKin,
                    NextOfKinPhone = d.NextOfKinPhone,
                    GuardianName = d.GuardianName,
                    GuardianIdcode = d.GuardianIdcode,
                    Notes1 = d.Notes1,
                    Notes2 = d.Notes2,
                    Notes3 = d.Notes3,
                    Notes4 = d.Notes4,
                    Notes5 = d.Notes5,
                    UserNotes1 = d.UserNotes1,
                    UserNotes2 = d.UserNotes2,
                    UserNotes3 = d.UserNotes3,
                    UserNotes4 = d.UserNotes4,
                    UserNotes5 = d.UserNotes5
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task details by patient id: {PatientId}", patientId);
                throw;
            }
        }

        public async Task<long> CreateAsync(RefundTaskDetailCreateRequest request)
        {
            try
            {
                var detail = new RefundTaskDetail
                {
                    MasterId = request.MasterId,
                    PatientId = request.PatientId,
                    AccountId = request.AccountId,
                    AccountIndex = request.AccountIndex,
                    Balance = request.Balance,
                    ContactCount = request.ContactCount,
                    ContactTime1 = request.ContactTime1?.ToUniversalTime(),
                    ContactTime2 = request.ContactTime2?.ToUniversalTime(),
                    ContactTime3 = request.ContactTime3?.ToUniversalTime(),
                    ContactTime4 = request.ContactTime4?.ToUniversalTime(),
                    ContactTime5 = request.ContactTime5?.ToUniversalTime(),
                    PhoneNumber = request.PhoneNumber,
                    PatName = request.PatName,
                    IdNumber = request.IdNumber,
                    Sex = request.Sex,
                    NextOfKin = request.NextOfKin,
                    NextOfKinPhone = request.NextOfKinPhone,
                    GuardianName = request.GuardianName,
                    GuardianIdcode = request.GuardianIdcode,
                    Notes1 = request.Notes1,
                    Notes2 = request.Notes2,
                    Notes3 = request.Notes3,
                    Notes4 = request.Notes4,
                    Notes5 = request.Notes5,
                    UserNotes1 = request.UserNotes1,
                    UserNotes2 = request.UserNotes2,
                    UserNotes3 = request.UserNotes3,
                    UserNotes4 = request.UserNotes4,
                    UserNotes5 = request.UserNotes5
                };

                return await _repository.CreateAsync(detail);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating refund task detail");
                throw;
            }
        }

        public async Task<bool> UpdateAsync(long id, RefundTaskDetailUpdateRequest request)
        {
            try
            {
                var existing = await _repository.GetByIdAsync(id);
                if (existing == null) return false;

                existing.MasterId = request.MasterId;
                existing.PatientId = request.PatientId;
                existing.AccountId = request.AccountId;
                existing.AccountIndex = request.AccountIndex;
                existing.Balance = request.Balance;
                existing.ContactCount = request.ContactCount;
                existing.ContactTime1 = request.ContactTime1?.ToUniversalTime();
                existing.ContactTime2 = request.ContactTime2?.ToUniversalTime();
                existing.ContactTime3 = request.ContactTime3?.ToUniversalTime();
                existing.ContactTime4 = request.ContactTime4?.ToUniversalTime();
                existing.ContactTime5 = request.ContactTime5?.ToUniversalTime();
                existing.PhoneNumber = request.PhoneNumber;
                existing.PatName = request.PatName;
                existing.IdNumber = request.IdNumber;
                existing.Sex = request.Sex;
                existing.NextOfKin = request.NextOfKin;
                existing.NextOfKinPhone = request.NextOfKinPhone;
                existing.GuardianName = request.GuardianName;
                existing.GuardianIdcode = request.GuardianIdcode;
                // 添加缺失的Notes和UserNotes字段
                existing.Notes1 = request.Notes1;
                existing.Notes2 = request.Notes2;
                existing.Notes3 = request.Notes3;
                existing.Notes4 = request.Notes4;
                existing.Notes5 = request.Notes5;
                existing.UserNotes1 = request.UserNotes1;
                existing.UserNotes2 = request.UserNotes2;
                existing.UserNotes3 = request.UserNotes3;
                existing.UserNotes4 = request.UserNotes4;
                existing.UserNotes5 = request.UserNotes5;

                return await _repository.UpdateAsync(existing);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating refund task detail: {Id}", id);
                throw;
            }
        }

        public async Task<bool> DeleteAsync(long id)
        {
            try
            {
                return await _repository.DeleteAsync(id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting refund task detail: {Id}", id);
                throw;
            }
        }

        public async Task<bool> DeleteByMasterIdAsync(long masterId)
        {
            try
            {
                return await _repository.DeleteByMasterIdAsync(masterId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting refund task details by master id: {MasterId}", masterId);
                throw;
            }
        }

        public async Task<bool> UpdateContactTimeAsync(ContactUpdateRequest request)
        {
            try
            {
                return await _repository.UpdateContactTimeAsync(request.Id, request.ContactTime);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating contact time for refund task detail: {Id}", request.Id);
                throw;
            }
        }

        public async Task<bool> BatchCreateAsync(BatchCreateTaskDetailRequest request)
        {
            try
            {
                var details = request.Details.Select(d => new RefundTaskDetail
                {
                    MasterId = request.MasterId,
                    PatientId = d.PatientId,
                    AccountId = d.AccountId,
                    AccountIndex = d.AccountIndex,
                    Balance = d.Balance,
                    ContactCount = d.ContactCount,
                    ContactTime1 = d.ContactTime1?.ToUniversalTime(),
                    ContactTime2 = d.ContactTime2?.ToUniversalTime(),
                    ContactTime3 = d.ContactTime3?.ToUniversalTime(),
                    ContactTime4 = d.ContactTime4?.ToUniversalTime(),
                    ContactTime5 = d.ContactTime5?.ToUniversalTime(),
                    PhoneNumber = d.PhoneNumber,
                    PatName = d.PatName,
                    IdNumber = d.IdNumber,
                    Sex = d.Sex,
                    NextOfKin = d.NextOfKin,
                    NextOfKinPhone = d.NextOfKinPhone,
                    GuardianName = d.GuardianName,
                    GuardianIdcode = d.GuardianIdcode,
                    Notes1 = d.Notes1,
                    Notes2 = d.Notes2,
                    Notes3 = d.Notes3,
                    Notes4 = d.Notes4,
                    Notes5 = d.Notes5,
                    UserNotes1 = d.UserNotes1,
                    UserNotes2 = d.UserNotes2,
                    UserNotes3 = d.UserNotes3,
                    UserNotes4 = d.UserNotes4,
                    UserNotes5 = d.UserNotes5
                });

                return await _repository.BatchCreateAsync(details);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error batch creating refund task details");
                throw;
            }
        }
    }
}